package bsts.view.subscription;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import bsts.model.Feature;

public class AddFeaturePanel extends JPanel {

	private static final long serialVersionUID = 1L;

	private JPanel pnlMain;
	private JPanel pnlButtons;

	private JTable tblAvailableFeatures;
	private JScrollPane scrAvailableFeatures;
	private JTable tblSelectedFeatures;
	private JScrollPane scrSelectedFeatures;

	private JButton btnAddAll;
	private JButton btnAdd;
	private JButton btnRemove;
	private JButton btnRemoveAll;

	private ArrayList<Feature> availableFeatures;
	private ArrayList<Feature> selectedFeatures;
	private ArrayList<Feature> orgSelectedFeatures;

	private ActionListener actlis_btnAddAll;
	private ActionListener actlis_btnAdd;
	private ActionListener actlis_btnRemove;
	private ActionListener actlis_btnRemoveAll;

	public AddFeaturePanel(ArrayList<Feature> availableFeatures) {
		this.availableFeatures = availableFeatures;
		this.selectedFeatures = new ArrayList<Feature>();

		pnlMain = new JPanel();
		pnlButtons = new JPanel();

		pnlMain.setLayout(new BorderLayout());
		pnlButtons.setLayout(new GridLayout(4, 1, 0, 5));

		pnlMain.setBorder(BorderFactory.createTitledBorder("Feature"));

		btnAddAll = new JButton(">>");
		btnAdd = new JButton(">");
		btnRemove = new JButton("<");
		btnRemoveAll = new JButton("<<");

		tblAvailableFeatures = new JTable();
		scrAvailableFeatures = new JScrollPane();

		tblSelectedFeatures = new JTable();
		scrSelectedFeatures = new JScrollPane();

		initSelectedFeatures();
		initTblAvailableFeatures();
		initTblSelectedFeatures();
		scrAvailableFeatures
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrAvailableFeatures.add(tblAvailableFeatures, null);
		scrAvailableFeatures.setViewportView(tblAvailableFeatures);
		scrAvailableFeatures.setPreferredSize(new Dimension(350, 150));

		scrSelectedFeatures
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrSelectedFeatures.add(tblSelectedFeatures, null);
		scrSelectedFeatures.setViewportView(tblSelectedFeatures);
		scrSelectedFeatures.setPreferredSize(new Dimension(350, 150));

		pnlButtons.add(btnAddAll);
		pnlButtons.add(btnAdd);
		pnlButtons.add(btnRemove);
		pnlButtons.add(btnRemoveAll);

		pnlMain.add(scrAvailableFeatures, BorderLayout.WEST);
		pnlMain.add(pnlButtons, BorderLayout.CENTER);
		pnlMain.add(scrSelectedFeatures, BorderLayout.EAST);

		this.add(pnlMain);

		initActionListener();
	}

	@SuppressWarnings("unchecked")
	public AddFeaturePanel(ArrayList<Feature> availableFeatures,
			ArrayList<Feature> selectedFeatures) {
		this.availableFeatures = availableFeatures;
		this.orgSelectedFeatures = selectedFeatures;
		this.selectedFeatures = (ArrayList<Feature>) selectedFeatures.clone();

		pnlMain = new JPanel();
		pnlButtons = new JPanel();

		pnlMain.setLayout(new BorderLayout());
		pnlButtons.setLayout(new GridLayout(4, 1, 0, 5));

		pnlMain.setBorder(BorderFactory.createTitledBorder("Features"));

		btnAddAll = new JButton(">>");
		btnAdd = new JButton(">");
		btnRemove = new JButton("<");
		btnRemoveAll = new JButton("<<");

		tblAvailableFeatures = new JTable();
		scrAvailableFeatures = new JScrollPane();

		tblSelectedFeatures = new JTable();
		scrSelectedFeatures = new JScrollPane();

		initAvailableFeatures();
		initTblAvailableFeatures();
		initTblSelectedFeatures();
		scrAvailableFeatures
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrAvailableFeatures.add(tblAvailableFeatures, null);
		scrAvailableFeatures.setViewportView(tblAvailableFeatures);
		scrAvailableFeatures.setPreferredSize(new Dimension(350, 150));

		scrSelectedFeatures
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrSelectedFeatures.add(tblSelectedFeatures, null);
		scrSelectedFeatures.setViewportView(tblSelectedFeatures);
		scrSelectedFeatures.setPreferredSize(new Dimension(350, 150));

		pnlButtons.add(btnAddAll);
		pnlButtons.add(btnAdd);
		pnlButtons.add(btnRemove);
		pnlButtons.add(btnRemoveAll);

		pnlMain.add(scrAvailableFeatures, BorderLayout.WEST);
		pnlMain.add(pnlButtons, BorderLayout.CENTER);
		pnlMain.add(scrSelectedFeatures, BorderLayout.EAST);

		this.add(pnlMain);

		initActionListener();
	}

	private void initSelectedFeatures() {
		for (int i = 0; i < availableFeatures.size();) {
			if (availableFeatures.get(i).isDefaultFeature())
				selectedFeatures.add(availableFeatures.remove(i));
			else
				i++;
		}
	}

	private void initAvailableFeatures() {
		for (int i = 0; i < availableFeatures.size();) {
			boolean match = false;

			for (int j = 0; j < selectedFeatures.size(); j++) {
				if (availableFeatures.get(i).getFeatureId() == selectedFeatures
						.get(j).getFeatureId()) {
					match = true;
					break;
				}
			}

			if (match)
				availableFeatures.remove(i);
			else
				i++;
		}
	}

	private void initTblAvailableFeatures() {
		final String[] strHeaded = { "Name", "Rate", "Type" };

		// Create a model of the data.
		TableModel dataModel = new AbstractTableModel() {
			private static final long serialVersionUID = 1L;

			public int getColumnCount() {
				return strHeaded.length;
			}

			public int getRowCount() {
				return availableFeatures.size();
			}

			public Object getValueAt(int row, int col) {
				Feature feature = availableFeatures.get(row);

				if (col == 0) {
					return feature.getName();
				} else if (col == 1) {
					return feature.getRate();
				} else if (col == 2) {
					return feature.getRateType();
				} else {
					return null;
				}
			}

			public String getColumnName(int column) {
				return strHeaded[column];
			}

			public Class<?> getColumnClass(int col) {
				return getValueAt(0, col).getClass();
			}
		};

		tblAvailableFeatures = new JTable(dataModel);
		tblAvailableFeatures.getSelectionModel();
		tblAvailableFeatures
				.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		DefaultTableCellRenderer right = new DefaultTableCellRenderer();
		right.setHorizontalAlignment(DefaultTableCellRenderer.TRAILING);

		tblAvailableFeatures.setDefaultRenderer(Object.class, right);

		int[] intWidth = { 150, 125, 125 };

		for (int i = 0; i < intWidth.length; i++) {
			TableColumn tblCol = tblAvailableFeatures.getColumn(strHeaded[i]);
			tblCol.setMaxWidth(intWidth[i]);
		}
	}

	private void initTblSelectedFeatures() {
		final String[] strHeaded = { "Name", "Rate", "Type" };

		// Create a model of the data.
		TableModel dataModel = new AbstractTableModel() {
			private static final long serialVersionUID = 1L;

			public int getColumnCount() {
				return strHeaded.length;
			}

			public int getRowCount() {
				return selectedFeatures.size();
			}

			public Object getValueAt(int row, int col) {
				Feature feature = selectedFeatures.get(row);

				if (col == 0) {
					return feature.getName();
				} else if (col == 1) {
					return feature.getRate();
				} else if (col == 2) {
					return feature.getRateType();
				} else {
					return null;
				}
			}

			public String getColumnName(int column) {
				return strHeaded[column];
			}

			public Class<?> getColumnClass(int col) {
				return getValueAt(0, col).getClass();
			}
		};

		tblSelectedFeatures = new JTable(dataModel);
		tblSelectedFeatures.getSelectionModel();
		tblSelectedFeatures
				.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		DefaultTableCellRenderer right = new DefaultTableCellRenderer();
		right.setHorizontalAlignment(DefaultTableCellRenderer.TRAILING);

		tblSelectedFeatures.setDefaultRenderer(Object.class, right);

		int[] intWidth = { 200, 150, 150 };

		for (int i = 0; i < intWidth.length; i++) {
			TableColumn tblCol = tblSelectedFeatures.getColumn(strHeaded[i]);
			tblCol.setMaxWidth(intWidth[i]);
		}
	}

	public ArrayList<Feature> getSelectedFeatures() {
		return selectedFeatures;
	}
	
	public ArrayList<Feature> getAddedFeatures() {
		ArrayList<Feature> addedFeatures = new ArrayList<Feature>();
		
		for (Feature feature : selectedFeatures) {
			if (feature.getSubscriptionStatus() == null)
				addedFeatures.add(feature);
		}
		
		selectedFeatures = orgSelectedFeatures;
		return addedFeatures;
	}

	public void refreshTbl() {
		tblAvailableFeatures.revalidate();
		tblAvailableFeatures.repaint();

		tblSelectedFeatures.revalidate();
		tblSelectedFeatures.repaint();
	}

	private void initActionListener() {
		actlis_btnAddAll = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				for (int i = 0; i < availableFeatures.size();) {
					selectedFeatures.add(availableFeatures.remove(i));
				}

				refreshTbl();
			}
		};

		actlis_btnAdd = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (tblAvailableFeatures.getSelectedRow() >= 0) {
					selectedFeatures.add(availableFeatures
							.remove(tblAvailableFeatures.getSelectedRow()));

					refreshTbl();
				}
			}
		};

		actlis_btnRemove = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (tblSelectedFeatures.getSelectedRow() >= 0) {
					if (selectedFeatures.get(
							tblSelectedFeatures.getSelectedRow())
							.isDefaultFeature())
						JOptionPane.showMessageDialog(pnlMain.getParent(),
								"Default feature cannot be removed.");
					else if (selectedFeatures.get(
							tblSelectedFeatures.getSelectedRow())
							.getSubscriptionStatus() != null)
						JOptionPane.showMessageDialog(pnlMain.getParent(),
								"Activated feature cannot be removed.");
					else
						availableFeatures.add(selectedFeatures
								.remove(tblSelectedFeatures.getSelectedRow()));

					refreshTbl();
				}
			}
		};

		actlis_btnRemoveAll = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				for (int i = 0; i < selectedFeatures.size();) {
					if (!selectedFeatures.get(i).isDefaultFeature()
							|| (!selectedFeatures.get(i).isDefaultFeature() && selectedFeatures
									.get(i) == null))
						availableFeatures.add(selectedFeatures.remove(i));
					else
						i++;
				}

				refreshTbl();
			}
		};

		btnAddAll.addActionListener(actlis_btnAddAll);
		btnAdd.addActionListener(actlis_btnAdd);
		btnRemove.addActionListener(actlis_btnRemove);
		btnRemoveAll.addActionListener(actlis_btnRemoveAll);
	}
}
